package burubaka.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import net.arnx.jsonic.JSON;

import org.apache.commons.lang3.StringUtils;
import org.slim3.datastore.Datastore;

import burubaka.BurubakaConstants;
import burubaka.common.BurubakaUtil;
import burubaka.common.KeibaNiftyUtil;
import burubaka.common.NetkeibaUtil;
import burubaka.meta.RaceCardHorseMeta;
import burubaka.model.RaceCardHorse;
import burubaka.model.RaceInfo;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

/**
 * @author tk
 * 
 */
public class RaceCardHorseService {

	private static final Logger log = Logger.getLogger(RaceCardHorseService.class.getName());

	private RaceCardHorseMeta meta = new RaceCardHorseMeta();

	/**
	 * @param key
	 * @return RaceCardHorseList
	 */
	public List<RaceCardHorse> findByRaceCardHorseKey(Key key) {
		if (key == null) {
			return new ArrayList<RaceCardHorse>();
		}
		return Datastore.query(this.meta, key).sort(this.meta.horseNo.asc).asList();
	}

	/**
	 * @param raceInfo
	 * @return RaceCardHorseList
	 */
	public List<RaceCardHorse> getRaceCardHorseList(RaceInfo raceInfo) {
		return this.findByRaceCardHorseKey(raceInfo.getKey());
	}

	/**
	 * @param raceInfo
	 * @param text
	 * @return RaceCardHorseList
	 */
	public List<RaceCardHorse> getRaceCardHorseList(RaceInfo raceInfo, String text) {
		List<RaceCardHorse> list = this.findByRaceCardHorseKey(raceInfo.getKey());

		if (list == null || list.isEmpty()) {
			list = getRaceCardHorseList(text);
		}
		return list;
	}

	/**
	 * @param text
	 * @return RaceCardHorseList
	 */
	public List<RaceCardHorse> getRaceCardHorseListByURL(RaceInfo raceInfo) throws Exception {
		String text = getURLText(raceInfo);
		if (BurubakaUtil.isLocal(raceInfo.getDistrictClass())) {
			// 地方の場合
			return getLoclaRaceCardHorseList(text);
		}
		return getRaceCardHorseList(text);
	}

	/**
	 * @param input
	 * @param raceInfo
	 * @return boolean
	 */
	public boolean regist(Map<String, Object> input, RaceInfo raceInfo) {
		log.info(input.toString());
		RaceCardHorse[] rch = JSON.decode((String) input.get("rcHorseL"), RaceCardHorse[].class);

		// Map<String, Object> map =
		// JSON.decode((String)input.get("json"),HashMap.class);
		// List<String> horseNo = BurubakaUtil.getRequestArray(map, "horseNo");
		// List<String> horseNames = BurubakaUtil.getRequestArray(map,
		// "horseName");
		// List<String> memos = BurubakaUtil.getRequestArray(map, "memo");
		// List<String> sexAgeL = BurubakaUtil.getRequestArray(map, "sexAge");
		// List<String> weight = BurubakaUtil.getRequestArray(map, "weight");
		// List<String> jockeys = BurubakaUtil.getRequestArray(map, "jockey");

		Transaction tx = Datastore.beginTransaction();

		List<Key> old = gatKeyList(raceInfo.getKey());
		Datastore.delete(old);

		// List<RaceCardHorse> list =
		// RaceCardHorseService.getRaceCardHorseList(horseNo,horseNames,null,sexAgeL,weight,jockeys,memos,raceInfo.getKey());

		List<RaceCardHorse> list = RaceCardHorseService.getRaceCardHorseList(rch, raceInfo.getKey());

		Datastore.put(list);
		tx.commit();
		return true;
	}

	/**
	 * @param input
	 * @param raceInfo
	 * @return boolean
	 */
	public boolean regist(List<RaceCardHorse> list, RaceInfo raceInfo) {

		Transaction tx = Datastore.beginTransaction();

		Key key = raceInfo.getKey();
		List<Key> old = gatKeyList(key);
		Datastore.delete(old);

		for (RaceCardHorse rch : list) {
			if (key != null) {
				Key childKey = Datastore.allocateId(key, RaceCardHorse.class);
				rch.setKey(childKey);
			}
		}

		Datastore.put(list);
		tx.commit();
		return true;
	}

	/**
	 * @param rchorses
	 * @param key
	 * @return RaceCardHorseList
	 */
	public static List<RaceCardHorse> getRaceCardHorseList(RaceCardHorse[] rchorses, Key key) {
		List<RaceCardHorse> list = new ArrayList<RaceCardHorse>();
		for (RaceCardHorse rch : rchorses) {
			if (key != null) {
				Key childKey = Datastore.allocateId(key, RaceCardHorse.class);
				rch.setKey(childKey);
			}
			list.add(rch);
		}
		return list;
	}

	/**
	 * @param text
	 * @return RaceCardHorseList
	 */
	private List<RaceCardHorse> getRaceCardHorseList(String text) {

		List<RaceCardHorse> list = new ArrayList<RaceCardHorse>();

		String dataTbl = BurubakaUtil.substring("<div class=\"dataTbl\">", "</div>", text);

		if (dataTbl == null) {
			return new ArrayList<RaceCardHorse>();
		}

		ArrayList<String> waku = KeibaNiftyUtil.getWakuList(dataTbl);
		log.info(waku.toString());

		ArrayList<String> horseNo = KeibaNiftyUtil.getHorseNoList(dataTbl);
		log.info(horseNo.toString());

		ArrayList<String> horseNamesA = KeibaNiftyUtil.getHorseNameAList(dataTbl);
		log.info(horseNamesA.toString());

		ArrayList<String> horseNames = BurubakaUtil.removeATag(horseNamesA);
		log.info(horseNames.toString());

		ArrayList<String> memos = KeibaNiftyUtil.getMemoList(horseNamesA);
		log.info(memos.toString());

		ArrayList<String> sexAgeL = KeibaNiftyUtil.getSexAgeList(dataTbl);
		log.info(sexAgeL.toString());

		ArrayList<String> weight = KeibaNiftyUtil.getWeightList(dataTbl);
		log.info(weight.toString());

		ArrayList<String> jockeysA = KeibaNiftyUtil.getJockeyAList(dataTbl);
		log.info(jockeysA.toString());

		ArrayList<String> jockeys = BurubakaUtil.removeATag(jockeysA);
		log.info(jockeys.toString());

		list = getRaceCardHorseList(waku, horseNo, horseNames, horseNamesA, sexAgeL, weight, jockeys, memos, null);

		return list;
	}

	/**
	 * @param text
	 * @return RaceCardHorseList
	 */
	private List<RaceCardHorse> getLoclaRaceCardHorseList(String text) {

		List<RaceCardHorse> list = new ArrayList<RaceCardHorse>();

		List<String> trList = NetkeibaUtil.getHorseInfoAreaList(text);
		if (trList == null) {
			return new ArrayList<RaceCardHorse>();
		}

		List<String> wakueNoL = new ArrayList<String>();
		List<String> horseNoL = new ArrayList<String>();
		List<String> horseNameAL = new ArrayList<String>();
		List<String> horseNameL = new ArrayList<String>();
		List<String> memos = new ArrayList<String>();
		List<String> sexAgeL = new ArrayList<String>();
		List<String> weightL = new ArrayList<String>();
		List<String> jockeyL = new ArrayList<String>();

		for (String trStr : trList) {
			wakueNoL.add(NetkeibaUtil.getWakuNo(trStr));
			List<String> tempL = NetkeibaUtil.getHorseInfo(trStr);
			horseNoL.add(tempL.get(0));
			String horseNameA = NetkeibaUtil.getHorseNameA(trStr);
			horseNameAL.add(horseNameA);
			String horseName = BurubakaUtil.removeATag(horseNameA);
			horseNameL.add(horseName);
			sexAgeL.add(tempL.get(1));
			weightL.add(tempL.get(2));
			String jockey = NetkeibaUtil.getJockeyA(trStr);
			jockey = BurubakaUtil.removeATag(jockey);
			jockeyL.add(jockey);
			memos.add("");
		}

		list = getRaceCardHorseList(wakueNoL, horseNoL, horseNameL, horseNameAL, sexAgeL, weightL, jockeyL, memos, null);

		return list;
	}

	/**
	 * @param waku
	 * @param horseNo
	 * @param horseNames
	 * @param horseNamesA
	 * @param sexAgeL
	 * @param weight
	 * @param jockeys
	 * @param memos
	 * @param key
	 * @return RaceCardHorseList
	 */
	private List<RaceCardHorse> getRaceCardHorseList(List<String> waku, List<String> horseNo, List<String> horseNames,
			List<String> horseNamesA, List<String> sexAgeL, List<String> weight, List<String> jockeys,
			List<String> memos, Key key) {

		log.info(waku.toString());
		log.info(horseNo.toString());
		log.info(horseNames.toString());
		log.info(horseNamesA.toString());
		log.info(sexAgeL.toString());
		log.info(weight.toString());
		log.info(jockeys.toString());
		log.info(memos.toString());

		List<RaceCardHorse> list = new ArrayList<RaceCardHorse>();
		for (int i = 0; i < horseNames.size(); i++) {
			RaceCardHorse rch = new RaceCardHorse();
			rch.setHorseName(horseNames.get(i));
			if (BurubakaUtil.isNotEmpty(waku, i)) {
				rch.setWaku(waku.get(i));
			}
			if (BurubakaUtil.isNotEmpty(horseNo, i)) {
				rch.setHorseNo(horseNo.get(i));
			}
			if (BurubakaUtil.isNotEmpty(horseNamesA, i)) {
				rch.setHorseNameA(horseNamesA.get(i));
			}
			if (BurubakaUtil.isNotEmpty(horseNames, i)) {
				rch.setHorseName(horseNames.get(i));
			}
			if (BurubakaUtil.isNotEmpty(sexAgeL, i)) {
				rch.setSexAge(sexAgeL.get(i));
			}
			if (BurubakaUtil.isNotEmpty(weight, i)) {
				rch.setWeight(weight.get(i));
			}
			if (BurubakaUtil.isNotEmpty(jockeys, i)) {
				rch.setJockey(jockeys.get(i));
			}
			if (BurubakaUtil.isNotEmpty(memos, i)) {
				rch.setMemo(memos.get(i));
			}
			if (StringUtils.isNotEmpty(rch.getMemo())) {
				rch.setExclusionFlg(true);
			}
			if (key != null) {
				Key childKey = Datastore.allocateId(key, RaceCardHorse.class);
				rch.setKey(childKey);
			}
			list.add(rch);
		}
		return list;
	}

	/**
	 * @param url
	 * @return URLText
	 * @throws Exception
	 */
	public static String getURLText(RaceInfo raceInfo) throws Exception {
		String url = raceInfo.getRaceURL();
		if (BurubakaUtil.isLocal(raceInfo.getDistrictClass())) {
			return NetkeibaUtil.getURLText(url, BurubakaConstants.BASE_URL_RC_LOCAL);
		}
		return KeibaNiftyUtil.getURLText(url, BurubakaConstants.BASE_URL_RC);
	}

	/**
	 * @param text
	 * @return URLText
	 * @throws Exception
	 */
	public static Date getStartTime(RaceInfo raceInfo) throws Exception {
		String text = getURLText(raceInfo);
		if (BurubakaUtil.isLocal(raceInfo.getDistrictClass())) {
			return NetkeibaUtil.getStartDate(text);
		}
		return KeibaNiftyUtil.getStartDate(text);
	}

	/**
	 * @param text
	 * @return URLText
	 * @throws Exception
	 */
	public static Date getDeadline(RaceInfo raceInfo) throws Exception {
		Date startTime = raceInfo.getStartTime();
		if (startTime == null) {
			String text = getURLText(raceInfo);
			if (BurubakaUtil.isLocal(raceInfo.getDistrictClass())) {
				return NetkeibaUtil.getDeadline(text);
			}
			return KeibaNiftyUtil.getDeadline(text);
		}

		return BurubakaUtil.getDeadline(startTime);
	}

	/**
	 * 全削除
	 * 
	 * @param raceInfo
	 * @return true:成功
	 */
	public boolean deleteAll(RaceInfo raceInfo) {
		Transaction tx = Datastore.beginTransaction();
		Datastore.delete(gatKeyList(raceInfo.getKey()));
		tx.commit();
		return true;
	}

	private List<Key> gatKeyList(Key key) {
		if (key == null) {
			return new ArrayList<Key>();
		}
		return Datastore.query(this.meta, key).asKeyList();
	}

}
